package com.car.account.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.car.account.controller.form.userForm.UserCodeLoginForm;
import com.car.account.controller.form.userForm.UserCodeRegisterForm;
import com.car.account.controller.form.userForm.UserPassLoginForm;
import com.car.account.entity.User;
import com.car.account.exception.AccountException;
import com.car.account.mapper.UserMapper;
import com.car.account.param.userParam.UserRealNameParam;
import com.car.account.rabbitmq.SendLoginCodeConsumer;
import com.car.account.rabbitmq.SendRegisterCodeConsumer;
import com.car.account.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.car.account.util.aliyunUtil.AliyunIDcardValidator;
import com.car.account.util.aliyunUtil.AliyunOssUtil;
import com.car.account.util.validatorUtil.IDCardValidator;
import com.car.account.util.validatorUtil.PasswordValidator;
import com.car.account.util.validatorUtil.PhoneNumberValidator;
import com.car.account.util.UserNicknameGenerator;
import com.car.commons.web.util.MD5util;
import com.car.commons.web.util.RedisKeyUtil;
import com.car.commons.web.util.RedisUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 董旭
 * @since 2024-08-28
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserService userService;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private SendLoginCodeConsumer sendLoginCodeConsumer;

    @Resource
    private SendRegisterCodeConsumer sendRegisterCodeConsumer;

    @Resource
    private AliyunOssUtil aliyunOssUtil;

    @Override
    public Integer userPassLogin(UserPassLoginForm form) throws Exception{
        //判断手机号格式是否正常
        if (!PhoneNumberValidator.isValidPhoneNumber(form.getUserPhone()))
            throw new AccountException(1111,"手机号不符合规范");
        //验证密码格式
        if (!PasswordValidator.isValidPassword(form.getUserPass())) throw new AccountException(1112,"密码格式不正确");
        //判断手机号是否存在
        User user = userService.getOne(new QueryWrapper<User>()
                .eq("user_phone", form.getUserPhone())
                .ne("user_state", 2));
        if (user == null) throw new AccountException(1000,"用户不存在");
        //判断状态
        if (user.getUserState() == 1) throw new AccountException(1002,"用户已被禁用");
        //判断用户密码是否正确
        if (!(MD5util.md5(form.getUserPhone(),form.getUserPass()).equals(user.getUserPass())))
            throw new AccountException(1003,"密码错误");
        return user.getUserId();
    }

    @Override
    public void sendUserLoginCode(String userPhone) throws Exception{
        //判断手机号格式是否正常
        if (!PhoneNumberValidator.isValidPhoneNumber(userPhone))
            throw new AccountException(1111,"手机号不符合规范");
        //判断手机号是否存在
        User user = userService.getOne(new QueryWrapper<User>()
                .eq("user_phone", userPhone)
                .ne("user_state", 2));
        if (user == null) throw new AccountException(1000,"用户不存在");
        //判断状态
        if (user.getUserState() == 1) throw new AccountException(1002,"用户已被禁用");
        //判断一分钟内重复发送
        if (redisUtil.hasKey(RedisKeyUtil.loginCodeOnMinute(userPhone)))
            throw new AccountException(1003,"请勿在1分钟内重复发送");
        //判断一小时内发送次数
        if (!redisUtil.hasKey(RedisKeyUtil.sendNumbers(userPhone))) {
            redisUtil.set(RedisKeyUtil.sendNumbers(userPhone), "1", 60*60);
        }
        String num = redisUtil.get(RedisKeyUtil.sendNumbers(userPhone));
        if (!num.isEmpty() && Integer.parseInt(num) >= 5) {
            throw new AccountException(1004,"一小时内发送验证码超出5条，稍后再试");
        }
        //信息队列发送验证码并保存redis
        sendLoginCodeConsumer.sendLoginCode(userPhone);
    }

    @Override
    public Integer userCodeLogin(UserCodeLoginForm form) throws Exception {
        //判断手机号格式是否正常
        if (!PhoneNumberValidator.isValidPhoneNumber(form.getUserPhone()))
            throw new AccountException(1111,"手机号不符合规范");
        //判断是否存在用户
        User user = userService.getOne(new QueryWrapper<User>()
                .eq("user_phone", form.getUserPhone())
                .ne("user_state", 2));
        if (user == null) throw new AccountException(1000,"用户不存在");
        //判断状态
        if (user.getUserState() == 1) throw new AccountException(1002,"用户已被禁用");
        //验证验证码
        if (!redisUtil.hasKey(RedisKeyUtil.loginCodeKey(form.getUserPhone())))
            throw new AccountException(1005,"无效验证码");
        String code = redisUtil.get(RedisKeyUtil.loginCodeKey(form.getUserPhone()));
        if (!code.equals(form.getCode()))
            throw new AccountException(1006,"验证码有误");
        //删除redis验证码
        redisUtil.del(RedisKeyUtil.loginCodeKey(form.getUserPhone()));
        return user.getUserId();
    }

    @Override
    public void sendUserRegisterCode(String userPhone) throws Exception {
        //判断手机号格式是否正常
        if (!PhoneNumberValidator.isValidPhoneNumber(userPhone))
            throw new AccountException(1111,"手机号不符合规范");
        //判断是否已经被注册
        User user = userService.getOne(new QueryWrapper<User>()
                .eq("user_phone", userPhone)
                .ne("user_state", 2));
        if (user != null) throw new AccountException(1006,"手机号已被注册");
        //判断一分钟内重复发送
        if (redisUtil.hasKey(RedisKeyUtil.registerCodeOnMinute(userPhone)))
            throw new AccountException(1003,"请勿在1分钟内重复发送");
        //判断一小时内发送次数
        if (!redisUtil.hasKey(RedisKeyUtil.sendNumbers(userPhone))) {
            redisUtil.set(RedisKeyUtil.sendNumbers(userPhone), "1", 60*60);
        }
        String num = redisUtil.get(RedisKeyUtil.sendNumbers(userPhone));
        if (!num.isEmpty() && Integer.parseInt(num) >= 5) {
            throw new AccountException(1004,"一小时内发送验证码超出5条，稍后再试");
        }
        //信息队列发送验证码并保存redis
        sendRegisterCodeConsumer.sendRegisterCode(userPhone);
    }

    @Override
    @Transactional
    public void userCodeRegister(UserCodeRegisterForm form) throws Exception {
        //判断手机号格式是否正常
        if (!PhoneNumberValidator.isValidPhoneNumber(form.getUserPhone()))
            throw new AccountException(1111,"手机号不符合规范");
        //验证密码格式
        if (!PasswordValidator.isValidPassword(form.getUserPass())) throw new AccountException(1112,"密码格式不正确");
        //判断是否已经被注册
        User user = userService.getOne(new QueryWrapper<User>()
                .eq("user_phone", form.getUserPhone())
                .ne("user_state", 2));
        if (user != null) throw new AccountException(1007,"手机号已被注册");
        //验证验证码
        if (!redisUtil.hasKey(RedisKeyUtil.registerCodeKey(form.getUserPhone())))
            throw new AccountException(1005,"验证码失效");
        String code = redisUtil.get(RedisKeyUtil.registerCodeKey(form.getUserPhone()));
        if (!code.equals(form.getCode()))
            throw new AccountException(1006,"验证码有误");
        //删除redis验证码
        redisUtil.del(RedisKeyUtil.registerCodeKey(form.getUserPhone()));
        User addUser = new User();
        //添加用户信息
        addUser.setUserPhone(form.getUserPhone());
        addUser.setUserPass(MD5util.md5(form.getUserPhone(),form.getUserPass()));
        addUser.setUserNickname(UserNicknameGenerator.generateRandomUsername());
        addUser.setImage("https://superman-book.oss-cn-chengdu.aliyuncs.com/%E7%94%A8%E6%88%B7%E9%BB%98%E8%AE%A4%E5%A4%B4%E5%83%8F.png");
        addUser.setSilenceState(0);
        addUser.setUserState(0);
        save(addUser);
    }

    @Override
    @Transactional
    public void userRealName(UserRealNameParam param) throws Exception {
        //判断是否存在用户
        User user = userService.getById(param.getUserId());
        if (user == null || user.getUserState() == 2) throw new AccountException(1000,"用户不存在");
        //判断状态
        if (user.getUserState() == 1) throw new AccountException(1002,"用户已被禁用");
        //判断身份证格式
        if (!IDCardValidator.isValidIDCard(param.getNum())) throw new AccountException(1003,"身份证格式有误");
        //判断身份证是否被注册
        if (userService.getOne(new QueryWrapper<User>().eq("user_num", param.getNum())) != null)
            throw new AccountException(1004,"身份证已被注册");
        //云亿互通实名认证
        AliyunIDcardValidator.postData(param.getUserName(),param.getNum());
        //更新账号身份证和姓名
        user.setUserNum(param.getNum());
        user.setUserName(param.getUserName());
        updateById(user);
    }

    @Override
    @Transactional
    public void updateUserPhoneById(Integer userId, String userPhone) throws Exception {
        //判断手机号格式是否正常
        if (!PhoneNumberValidator.isValidPhoneNumber(userPhone))
            throw new AccountException(1111,"手机号不符合规范");
        //判断是否存在用户
        User user = userService.getById(userId);
        if (user == null || user.getUserState() == 2) throw new AccountException(1000,"用户不存在");
        //判断状态
        if (user.getUserState() == 1) throw new AccountException(1002,"用户已被禁用");
        //判断手机号是否被绑定
        User userByPhone = userService.getOne(new QueryWrapper<User>()
                .eq("user_phone", userPhone)
                .ne("user_state", 2));
        if (userByPhone != null) throw new AccountException(1003,"手机号已被绑定");
        //修改用户绑定手机号
        user.setUserPhone(userPhone);
        updateById(user);
    }

    @Override
    @Transactional
    public void updateUserPassById(Integer userId, String userPass) throws Exception {
        //判断是否存在用户
        User user = userService.getById(userId);
        if (user == null || user.getUserState() == 2) throw new AccountException(1000,"用户不存在");
        //判断状态
        if (user.getUserState() == 1) throw new AccountException(1002,"用户已被禁用");
        //验证密码格式
        if (!PasswordValidator.isValidPassword(userPass)) throw new AccountException(1112,"密码格式不正确");
        user.setUserPass(MD5util.md5(user.getUserPhone(),userPass));
        updateById(user);
    }

    @Override
    @Transactional
    public String userUpdateImage(MultipartFile mf, Integer userId) throws Exception {
        //判断是否存在用户
        User user = userService.getById(userId);
        if (user == null || user.getUserState() == 2) throw new AccountException(1000,"用户不存在");
        //判断状态
        if (user.getUserState() == 1) throw new AccountException(1002,"用户已被禁用");
        String imageName = aliyunOssUtil.upImage(mf);
        //修改头像
        user.setImage(imageName);
        updateById(user);
        return imageName;
    }

    @Override
    @Transactional
    public String userUpdateNickname(String userNickname, Integer userId) throws Exception {
        //判断是否存在用户
        User user = userService.getById(userId);
        if (user == null || user.getUserState() == 2) throw new AccountException(1000,"用户不存在");
        //判断状态
        if (user.getUserState() == 1) throw new AccountException(1002,"用户已被禁用");
        //修改昵称
        user.setUserNickname(userNickname);
        updateById(user);
        return null;
    }
}
